/**
 * Description:
 * Class Name:ForkJoinPoolTest2Sum
 * Date:2022/5/8 18:13
 *
 * @author LTisme
 * @version JAVA17
 */
package 疯狂Java讲义.第16章_多线程._16_8_线程池._16_8_2_使用ForkJoinPool;

import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;

class CalTask extends RecursiveTask<Integer>{
    // 每个小任务的上限
    private static final int THRESHOLD = 20;
    private int arr[];
    private int start;
    private int end;
    // 累加从start到end的数组元素
    public CalTask(int[] arr, int start, int end){
        this.arr = arr;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        int sum = 0;
        if (end - start < THRESHOLD){
            for (int i = start; i < end; i++) {
                sum += arr[i];
            }
            return sum;
        }
        else {
            // 任务分解
            int middle = (start + end) / 2;
            var left = new CalTask(arr, start, middle);
            var right = new CalTask(arr, middle, end);
            left.fork();
            right.fork();
            // 把两个小任务累加的结果合并起来
            return left.join() + right.join();
        }
    }
}

public class ForkJoinPoolTest2Sum {
    public static void main(String[] args) throws Exception{
        var arr = new int[100];
        var rand = new Random();
        var total = 0;
        for (int i = 0; i < arr.length; i++) {
            int tmp = rand.nextInt(20);
            total += (arr[i] = tmp);
        }
        System.out.println("for循环的累加和：" + total);
        // 创建一个通用池
        ForkJoinPool pool = ForkJoinPool.commonPool();
        // 提交可分解的CalTask任务
        Future<Integer> future = pool.submit(new CalTask(arr, 0, arr.length));
        System.out.println("使用通用线程池的累加和：" + future.get());
        pool.shutdown();
    }
}
